import log from '../../../helpers/logger';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
//import { validateLink } from '../../../helpers/dataValidation';

import {
  authorizedRouteHandler,
  ControllerMethodTypes,
  defaultRouteHandler,
} from '../../../../interfaces';
import { Request } from 'hyper-express';
import { showSelectedObjectKeys } from '../../../helpers/utilsJS';
import { wechat_menus } from '../../../../../prisma/generated/uctoo';
import { setExCache } from '../../../helpers/redis';
import { OfficialAccount, ServerRequest, FormData, defineOfficialAccountConfig, defineOpenPlatformConfig, OpenPlatform } from 'node-easywechat';
import Message from 'node-easywechat';
import { queryAdminAppletsFromDatabase } from '../../../services/uctoo/admin_applet';
import {
  createWechatopen,
  deleteWechatopenFromDatabase,
  editWechatopenInDatabase,
  getWechatopenFromDatabase,
  getWechatopensFromDatabase,
  queryWechatopensFromDatabase,
  getFirstWechatopenFromDatabase
} from '../../../services/uctoo/wechatopen';
import {
  createWechatopenApplet,
  deleteWechatopenAppletFromDatabase,
  editWechatopenAppletInDatabase,
  getWechatopenAppletFromDatabase,
  getWechatopenAppletsFromDatabase,
  queryWechatopenAppletsFromDatabase
} from '../../../services/uctoo/wechatopen_applet';
import db from '../../../lib/db';
import DbCacher from '../../../lib/DbCacher';
import { dateToTimestampWithTimezone } from '../../../helpers/utilsJS';
  //#region AutoCreateCode
import {
  createWechatMenus,
  deleteWechatMenusFromDatabase,
  deleteMultiWechatMenusFromDatabase,
  editWechatMenusInDatabase,
  editMultiWechatMenusInDatabase,
  getWechatMenusFromDatabase,
  getWechatMenussFromDatabase,
  queryWechatMenussFromDatabase,
  countWechatMenuss
} from '../../../services/uctoo/wechat_menus';

class uctooWechatMenusController {

  protected validateAndDestructureBody = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const body = await req.json();
    const keysArray = Object.keys(body);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooWechatMenus = showSelectedObjectKeys(body, keysArray) as wechat_menus;
    uctooWechatMenus.creator = userId;

    return uctooWechatMenus;
  };
  public add: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const uctooWechatMenus = await this.validateAndDestructureBody(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      if (!uctooWechatMenus) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

      const createdWechatMenus = await createWechatMenus(uctooWechatMenus);
      if (!createdWechatMenus) return res.status(500).json({ errno: "50001", errmsg: "database query failed" });

      res.status(200).json(createdWechatMenus);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public edit: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id,ids,force } = body;

      if(ids){
        const uctooWechatMenus = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooWechatMenus) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedWechatMenus = await editMultiWechatMenusInDatabase(uctooWechatMenus, JSON.parse(ids), user);
        
        if (typeof editedWechatMenus === 'object' && 'success' in editedWechatMenus) {
          if (!editedWechatMenus.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: editedWechatMenus.reason,
              ...(editedWechatMenus.wechatMenusId && { wechatMenusId: editedWechatMenus.wechatMenusId })
            });
          }
          return res.status(200).json(editedWechatMenus.data);
        }
        
        res.status(200).json(editedWechatMenus);
      }else{
        const uctooWechatMenus = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooWechatMenus) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedWechatMenus = await editWechatMenusInDatabase(uctooWechatMenus, uctooWechatMenus.id, user);
        
        if (typeof editedWechatMenus === 'object' && 'success' in editedWechatMenus) {
          if (!editedWechatMenus.success) {
            return res.status(403).json({ errno: "40301", errmsg: editedWechatMenus.reason });
          }
          return res.status(200).json(editedWechatMenus.data);
        }
        res.status(200).json(editedWechatMenus);
      }      
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public delete: authorizedRouteHandler = async (req, res) => {
    try {
      const body = await req.json();
      const { id,ids,force } = body;
      const user = res.locals.id.user;

      if(ids){
        const deletionResult = await deleteMultiWechatMenusFromDatabase(JSON.parse(ids), force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: deletionResult.reason,
              ...(deletionResult.wechatMenusId && { wechatMenusId: deletionResult.wechatMenusId })
            });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }else{
        const deletionResult = await deleteWechatMenusFromDatabase(id, force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({ errno: "40301", errmsg: deletionResult.reason });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }

      res.status(200).json({ desc: '删除成功' });
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getSingle: authorizedRouteHandler = async (req, res) => {
    try {
      const { id } = req.params;
      const user = res.locals.id.user;

      const wechatMenusFromDb = await getWechatMenusFromDatabase(id, user);
      if (!wechatMenusFromDb) {
        return res.status(404).json({ 
          errno: "40401", 
          errmsg: '未找到该实体或您没有权限访问' 
        });
      }

      res.status(200).json(wechatMenusFromDb);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getMany: authorizedRouteHandler = async (req, res) => {
    try {
      const limit = parseInt(req.params.limit);
      const page = parseInt(req.params.page) || 0;
      const skip = parseInt(req.params.skip) || 0;
      const query = req.query;
      
      if (limit > 100) return res.status(400).json({ errno: "40002", errmsg: '请求数量不能超过100条' });
      if (isNaN(limit)) return res.status(400).json({ errno: "40003", errmsg: '请求数量必须是数字' });
      
      const user = res.locals.id.user;
      const totalCount = await countWechatMenuss(user);
      
      if (query) {
        const wechatMenussFromDb = await queryWechatMenussFromDatabase(limit, page, skip, query, user);
        if (!wechatMenussFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount: totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          wechatMenuss: wechatMenussFromDb
        });
      } else {
        const wechatMenussFromDb = await getWechatMenussFromDatabase(limit, skip, page, user);
        if (!wechatMenussFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount:totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          wechatMenuss: wechatMenussFromDb
        });
      }


    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  //#endregion AutoCreateCode

  //直接开发模式设置公众号菜单
  public setMenus: defaultRouteHandler = async (req, res) => {

    // 取出 wechatopen_applet数据
    const params: Record<string, any> = {};
    params.filter = JSON.stringify({ status: 1 });
    const adminApplet = await queryAdminAppletsFromDatabase(1, 0, 0, params);
    if (!adminApplet) return res.status(404).end();
    //log.info('adminApplet:', adminApplet);
    const waparams: Record<string, any> = {};
    waparams.filter = JSON.stringify({ appid: adminApplet[0].appid });
    const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, waparams);
    if (!wechatApplet) return res.status(404).end();
    //log.info('wechatApplet:', wechatApplet);
    try {
      const oa = defineOfficialAccountConfig({
        // 微信公众号的 app key
        app_id: wechatApplet[0].appid, //'wx2cdf8e0dffd4b2b2',
        // 微信公众号的 app secret
        secret: wechatApplet[0].appsecret,// '13be9d444b156f90fd175489fcb29c7c',
        // 微信公众号的 token
        token: wechatApplet[0].token,// 'uctoo',
        // EncodingAESKey
        aes_key: wechatApplet[0].aeskey,// 'uxo7tdM2iF5PQiQSLNfpdDD4k4X6ajVYJxEIxtxDYLg',
        // 网页授权认证
        oauth: {
          // 网页授权类型
          scope: 'snsapi_base',
          // 网页授权回调地址，完整的URL
          redirect_url: wechatApplet[0].redirect_url
        },
      })
      const wxapp = new OfficialAccount(oa);
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxapp.setRequest(request);

      const client = wxapp.getClient();
      const wxserver = wxapp.getServer();
      const getQrCodeUrl = process.env.API_URL + '/api/uctoo/minishop_order/createVmcOrderQrcode';

      const REDIRECT_URI = encodeURIComponent("https://demo.uctoo.com/pages/my/index");
      const userCenterURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wechatApplet[0].appid + "&redirect_uri=" + REDIRECT_URI + "&response_type=code&scope=snsapi_base&state=wechatMenu#wechat_redirect";

      let button = [
        {
          type: 'click',
          name: '今日新闻',
          key: 'TODAY_NEWS'
        },
        {
          name: '获取二维码',
          sub_button: [
            {
              type: 'view',
              name: '请香二维码',
              url: 'https://demo.uctoo.com/pages/home/OrderQrcode'    //getQrCodeUrl
            },
            {
              type: 'view',
              name: '中国新闻网',
              url: 'http://www.chinanews.com/'
            }
          ]
        },
        {
          name: '我的',
          sub_button: [
            {
              type: 'view',
              name: '个人中心',
              url: userCenterURL
            }
          ]
        }
      ];
      let result = (await client.post('cgi-bin/menu/create', {
        data: {
          button,
        },
      })).toObject();
      console.log('create-menu', result);

      // console.log('current-menu', await client.get('cgi-bin/get_current_selfmenu_info'));

      // // 销毁菜单
      // console.log('destory-menu', await client.get('cgi-bin/menu/delete'));
      // console.log('response', response);

      res.send('<meta name="viewport" content="width=device-width, initial-scale=1.0">菜单创建成功');

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }


  //微信第三方平台设置公众号菜单
  public wechatopenSetMenus: defaultRouteHandler = async (req, res) => {

    const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

    log.info({ info: 'wechatopensFromDb', wechatopenFromDb });


    const wechatopenConfig = defineOpenPlatformConfig({
      // 微信公众号的 app key
      app_id: wechatopenFromDb['appid'],
      // 微信公众号的 app secret
      secret: wechatopenFromDb['appsecret'],
      // 微信公众号的 token
      token: wechatopenFromDb['token'],
      // EncodingAESKey
      aes_key: wechatopenFromDb['encoding_aes_key'],

    })
    const wxopen = new OpenPlatform(wechatopenConfig);
    // const cat = wxopen.getComponentAccessToken();
    // wxopen.setComponentAccessToken();
    // log.info({ info: 'cat', cat });

    // 替换缓存实例
    let Dbcacher = new DbCacher(db);
    wxopen.setCache(Dbcacher);

    const body = await req.text();

    const request = new ServerRequest(
      req.method,
      req.url,
      req.headers,
      body,
      '1.1',
      req.query_parameters
    );
    wxopen.setRequest(request);

    const client = wxopen.getClient();
    const wxserver = wxopen.getServer();


    // 取出 wechatopen_applet数据
    const params: Record<string, any> = {};
    params.filter = JSON.stringify({ status: 1 });
    const adminApplet = await queryAdminAppletsFromDatabase(1, 0, 0, params);
    if (!adminApplet) return res.status(404).end();
    //log.info('adminApplet:', adminApplet);
    const waparams: Record<string, any> = {};
    waparams.filter = JSON.stringify({ appid: adminApplet[0].appid });
    const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, waparams);
    if (!wechatApplet) return res.status(404).end();
    //log.info('wechatApplet:', wechatApplet);
    try {
      /*  const oa = defineOfficialAccountConfig({
          // 微信公众号的 app key
          app_id: wechatApplet[0].appid, //'wx2cdf8e0dffd4b2b2',
          // 微信公众号的 app secret
          secret: wechatApplet[0].appsecret,// '13be9d444b156f90fd175489fcb29c7c',
          // 微信公众号的 token
          token: wechatApplet[0].token,// 'uctoo',
          // EncodingAESKey
          aes_key: wechatApplet[0].aeskey,// 'uxo7tdM2iF5PQiQSLNfpdDD4k4X6ajVYJxEIxtxDYLg',
          // 网页授权认证
          oauth: {
            // 网页授权类型
            scope: 'snsapi_base',
            // 网页授权回调地址，完整的URL
            redirect_url: wechatApplet[0].redirect_url
          },
        }) */

      const wxapp_access_token = await wxopen.getAuthorizerAccessToken(wechatApplet[0].appid, wechatApplet[0].authorizer_refresh_token);
      //根据token查询缓存，看token是否过期
      const nowTimestamp = Date.now();
      const cacheToken = await db.app_access_token.findFirst({
        where: {
          access_token: wxapp_access_token,
        },
      });
      if (cacheToken) {  //已有access_token缓存
        const dateWithTimezone = new Date(cacheToken.token_overtime); // 
        const tokenOvertimeTimestamp = dateToTimestampWithTimezone(dateWithTimezone);
        log.info({ info: 'tokenOvertimeTimestamp', timestamp: tokenOvertimeTimestamp }); // 输出时间戳

        if ((nowTimestamp + 20 * 60 * 1000) >= tokenOvertimeTimestamp) {  //差20分钟过期，重新获取component_access_token，sdk中没查询到缓存会掉接口重新获取
          //得先删除原缓存数据
          await Dbcacher.delete(cacheToken.id);
        }
      }

      log.info({ info: 'wxapp_access_token', wxapp_access_token: wxapp_access_token });

      //第三方平台开发公众号
      const wxapp = await wxopen.getOfficialAccountWithRefreshToken(wechatApplet[0].appid, wechatApplet[0].authorizer_refresh_token);
      log.info({ info: 'wxapp', wxapp: wxapp.getAccessToken() });
      //更新wechatopen_applet，不更新也行，只是为了wechatopen_applet和app_access_token缓存数据一致
      const date = new Date(nowTimestamp + 120 * 60 * 1000);  //authorizer_access_token两小时过期
      const newTokenOvertime = date.toISOString();
      const newToken = await wxapp.getAccessToken().getToken();
      const editedWechatopenApplet = await db.wechatopen_applet.update({
        data: { authorizer_access_token: newToken, access_token_overtime: newTokenOvertime },
        where: {
          id: wechatApplet[0].id,
        },
      });

      // const wxapp = new OfficialAccount(oa);
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const client = wxapp.getClient();

      // https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE&component_appid=component_appid#wechat_redirect
      const REDIRECT_URI = encodeURIComponent(wechatApplet[0].redirect_url);
      const userCenterURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wechatApplet[0].appid + "&redirect_uri=" + REDIRECT_URI + "&response_type=code&scope=snsapi_base&state=wechatMenu&component_appid=" + wechatopenFromDb['appid'] + "#wechat_redirect";

      let button = [
        {
          type: 'click',
          name: '今日要闻',
          key: 'TODAY_NEWS'
        },
        {
          name: '开源项目',
          sub_button: [
            {
              type: 'view',
              name: 'uctoo',
              url: 'https://gitee.com/uctoo/uctoo'    //getQrCodeUrl
            },
            {
              type: 'view',
              name: '数据库管理APP',
              url: 'https://atomgit.com/uctoo/uctoo-app'
            }
          ]
        },
        {
          name: '我的',
          sub_button: [
            {
              type: 'view',
              name: '个人中心',
              url: userCenterURL
            }
          ]
        }
      ];
      let result = (await client.post('cgi-bin/menu/create', {
        data: {
          button,
        },
      })).toObject();
      log.info({ info: 'create-menu', result: result });
      if (Number(result.errcode) === 0) {
        res.send('<meta name="viewport" content="width=device-width, initial-scale=1.0">第三方平台公众号菜单创建成功');
      } else if (Number(result.errcode) === 42001) { //authorizer_access_token过期
        res.send(`<meta name="viewport" content="width=device-width, initial-scale=1.0">第三方平台公众号菜单创建失败${result.errcode}:${result.errmsg}`);

      } else {
        res.send(`<meta name="viewport" content="width=device-width, initial-scale=1.0">第三方平台公众号菜单创建失败${result.errcode}:${result.errmsg}`);
      }

      // console.log('current-menu', await client.get('cgi-bin/get_current_selfmenu_info'));

      // // 销毁菜单
      // console.log('destory-menu', await client.get('cgi-bin/menu/delete'));
      // console.log('response', response);



    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

}

export default uctooWechatMenusController;
